package com.voodoo.lib_utils.imageLoader;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.MemoryCategory;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory;
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.RequestOptions;
import com.voodoo.lib_utils.R;
import com.voodoo.lib_utils.imageLoader.transformation.BlurTransformation;
import com.voodoo.lib_utils.imageLoader.transformation.GrayscaleTransformation;
import com.voodoo.lib_utils.imageLoader.transformation.RoundedCornersTransformation;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * Author：voodoo
 * CreateTime：2021/06/24 024 下午 01:02
 * Description：图片加载
 * 功能包括加载图片，圆形图片，圆角图片，指定圆角图片，模糊图片，灰度图片等等。
 * 目前我只加了这几个常用功能，其他请参考glide-transformations这个开源库。
 */
public class GlideImageLoader {

    private static final String TAG = "GlideImageLoader";

    private static final int placeholder = R.drawable.ic_icon_load_img_loading;
    private static final int error = R.drawable.icon_load_img_faild;

    private static final int CACHE_IMAGE_SIZE = 250; // 默认缓存大小 MB
    static GlideImageLoader glideImageLoader;
    static boolean isInit = false; // 是否初始化过该工具类
    static Context context;

    public static GlideImageLoader getInstance() {
        if (glideImageLoader == null) {
            glideImageLoader = new GlideImageLoader();
        }
        return glideImageLoader;
    }

    /**
     * 初始化
     *
     * @param context 上下文
     */
    public static void init(Context context) {
        init(context, CACHE_IMAGE_SIZE);
    }

    /**
     * 初始化
     *
     * @param context      上下文
     * @param cacheSizeInM Glide默认磁盘缓存最大容量250MB
     */
    public static void init(Context context, int cacheSizeInM) {
        init(context, cacheSizeInM, MemoryCategory.NORMAL);
    }

    /**
     * 初始化
     *
     * @param context        上下文
     * @param cacheSizeInM   Glide默认磁盘缓存最大容量250MB
     * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) ／ NORMAL(1f) ／ HIGH(1.5f);
     */
    public static void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory) {
        init(context, cacheSizeInM, memoryCategory, true);
    }

    /**
     * 初始化
     *
     * @param context        上下文
     * @param cacheSizeInM   Glide默认磁盘缓存最大容量250MB
     * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) ／ NORMAL(1f) ／ HIGH(1.5f);
     * @param isInternalCD   true 磁盘缓存到应用的内部目录 / false 磁盘缓存到外部存
     */
    public static void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
        isInit = true;
        GlideImageLoader.context = context;
        Glide.get(context).setMemoryCategory(memoryCategory); // 根据给定的 MemoryCategory 调整 Glide 的最大内存
        if (isInternalCD) {
            new GlideBuilder().setDiskCache(new InternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
        } else {
            new GlideBuilder().setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
        }
    }

    /**
     * 清理内存时执行此方法
     *
     * @param level 级别
     */
    public static void trimMemory(int level) {
        // 程序在内存清理的时候执行
        Glide.get(GlideImageLoader.context).trimMemory(level);
    }

    /**
     * 内存较低时执行此方法
     */
    public static void lowMemory() {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    Glide.get(GlideImageLoader.context).clearMemory();
                }
            });
        } else {
            Glide.get(GlideImageLoader.context).clearMemory();
        }
    }

    //============================================================================= 正常加载图片的方法

    /**
     * 默认加载图片
     *
     * @param context   上下文
     * @param url       图片地址url
     * @param imageView {@link ImageView}
     */
    public void loadImage(Context context, String url, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);
    }
    /**
     * 默认加载图片 是否去掉缓存
     *
     * @param context   上下文
     * @param url       图片地址url
     * @param imageView {@link ImageView}
     */
    public void loadImage(Context context, String url, ImageView imageView,boolean isCache) {
        RequestOptions options = new RequestOptions()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .skipMemoryCache(isCache)
                .diskCacheStrategy(DiskCacheStrategy.NONE);
        Glide.with(context).load(url).apply(options).into(imageView);
    }

    /**
     * 默认加载图片
     *
     * @param context   上下文
     * @param imgResId  资源图片
     * @param imageView {@link ImageView}
     */
    public void loadImage(Context context, int imgResId, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .fitCenter()
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(imgResId).apply(options).into(imageView);
    }

    /**
     * 加载Bitmap图片
     *
     * @param context   上下文
     * @param bitmap    Bitmap
     * @param imageView {@link ImageView}
     */
    public void loadBitmap(Context context, Bitmap bitmap, ImageView imageView) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] bytes = baos.toByteArray();
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(bytes).apply(options).into(imageView);
    }

    /**
     * 加载指定图片大小，无论ImageView多大，Glide都会将图片设置成 width * height 大小的图片
     * 如果想加载一张图片的原始尺寸的话，可以使用Target.SIZE_ORIGINAL关键字----override(Target.SIZE_ORIGINAL)
     *
     * @param context   上下文
     * @param url       图片地址url
     * @param imageView {@link ImageView}
     * @param width     图片宽
     * @param height    图片高
     */
    public void loadImageSize(Context context, String url, ImageView imageView, int width, int height) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .override(width, height)
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);
    }

    /**
     * 加载圆形图片
     *
     * @param context   上下文
     * @param url       图片Url
     * @param imageView {@link ImageView}
     */
    public void loadCircleImage(Context context, String url, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .circleCrop() // 设置圆形
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);
    }

    /**
     * 加载圆角图片
     *
     * @param context    上下文
     * @param url        图片Url
     * @param imageView  {@link ImageView}
     * @param radius     圆角半径
     * @param cornerType {@link RoundedCornersTransformation.CornerType}设置类别 ex.全圆角，左上圆角，左下圆角，上圆角，下圆角，对角圆角...
     */
    public void loadRoundCircleImage(Context context, String url, ImageView imageView, int radius, RoundedCornersTransformation.CornerType cornerType) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .circleCrop() // 设置圆形
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .bitmapTransform(new RoundedCornersTransformation(radius, 0, cornerType))
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);

    }

    /**
     * 加载模糊图片（自定义透明度）
     *
     * @param context   上下文
     * @param url       图片Url
     * @param imageView {@link ImageView}
     * @param blur      模糊度，一般1-100够了，越大越模糊
     */
    public void loadBlurImage(Context context, String url, ImageView imageView, int blur) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .bitmapTransform(new BlurTransformation(blur))
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);
    }

    /**
     * 加载灰度(黑白)图片（自定义透明度）
     *
     * @param context   上下文
     * @param url       图片Url
     * @param imageView {@link ImageView}
     */
    public void loadBlackImage(Context context, String url, ImageView imageView) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(new GlidePlaceholderErrorDrawable(context, placeholder))
                .error(new GlidePlaceholderErrorDrawable(context, error))
                .bitmapTransform(new GrayscaleTransformation())
                .diskCacheStrategy(DiskCacheStrategy.ALL);
        Glide.with(context).load(url).apply(options).into(imageView);
    }

    /**
     * 下载图片（将图片下载到本地并拷贝到指定文件中）
     *
     * @param context 上下文
     * @param url     图片Url
     */
    public void downloadImage(final Context context, final String url, final String saveImagePath$Name) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    FutureTarget<File> target = Glide.with(context)
                            .asFile()
                            .load(url)
                            .submit();
                    final File imageFile = target.get(); // 下载下来得到下载的文件
                    Log.i(TAG, "图片下载成功，回调给接口并记录下载图片地址：" + imageFile.getPath());

                    // 如果保存路径为null或为空字符串或者跟下载文件的地址一致，那么直接回调出去
                    if (saveImagePath$Name == null || saveImagePath$Name.equals("") || saveImagePath$Name.equals(imageFile.getPath())) {
                        Log.i(TAG, "直接将图片地址回调出去");
                        if (onImageDownloadListener != null) {
                            new Handler(Looper.getMainLooper()).post(new Runnable() {
                                @Override
                                public void run() {
                                    onImageDownloadListener.onImageDownload(true, url, imageFile);
                                }
                            });
                        }
                    } else {
                        Log.i(TAG, "需要拷贝到目标地址，直接拷贝文件");
                        boolean isCopySuccess = copyFile(imageFile.getPath(), saveImagePath$Name);
                        if (isCopySuccess) {
                            Log.i(TAG, "拷贝成功，将目标文件地址会掉出去，并将原始文件进行删除，防止占用太多的内部存储");
                            if (onImageDownloadListener != null) {
                                new Handler(Looper.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onImageDownloadListener.onImageDownload(true, url, new File(saveImagePath$Name));
                                    }
                                });
                            }
                            deleteFile(imageFile);
                        } else {
                            Log.i(TAG, "拷贝失败，将下载地址回调出去");
                            if (onImageDownloadListener != null) {
                                new Handler(Looper.getMainLooper()).post(new Runnable() {
                                    @Override
                                    public void run() {
                                        onImageDownloadListener.onImageDownload(true, url, imageFile);
                                    }
                                });
                            }
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 复制文件
     *
     * @param oldPath$Name 源文件路径以及文件名
     * @param newPath$Name 目标文件路径以及文件名
     * @return 操作结果，true：成功 反之失败
     */
    private boolean copyFile(String oldPath$Name, String newPath$Name) {
        try {
            File oldFile = new File(oldPath$Name);
            if (!oldFile.exists()) {
                Log.e(TAG, "copyFile: " + oldPath$Name + " 文件不存在！");
                return false;
            }
            if (!oldFile.isFile()) {
                Log.e(TAG, "copyFile: " + oldPath$Name + " 不是文件！");
                return false;
            }
            if (!oldFile.canRead()) {
                Log.e(TAG, "copyFile: " + oldPath$Name + " 文件不可读取！");
                return false;
            }

            FileInputStream fileInputStream = new FileInputStream(oldPath$Name);
            FileOutputStream fileOutputStream = new FileOutputStream(newPath$Name);
            byte[] buffer = new byte[1024];
            int byteRead;
            while (-1 != (byteRead = fileInputStream.read(buffer))) {
                fileOutputStream.write(buffer, 0, byteRead);
            }
            fileInputStream.close();
            fileOutputStream.flush();
            fileOutputStream.close();
            return true;
        } catch (Exception e) {
            Log.e(TAG, "copyFile: 复制文件异常！" + e.toString());
        }
        return false;
    }

    /**
     * 删除文件
     *
     * @param file 要删除的文件
     * @return 操作结果，true：成功 反之失败
     */
    private boolean deleteFile(File file) {
        if (file == null) {
            Log.e(TAG, "deleteFile: 文件为空，删个毛线啊！");
            return false;
        }
        if (!file.exists()) {
            Log.e(TAG, "deleteFile: 这个文件不存在啊！");
            return false;
        }
        if (!file.isFile()) {
            Log.e(TAG, "deleteFile: 这个不是文件，有可能是文件夹！");
            return false;
        }
        if (!file.canRead()) {
            Log.e(TAG, "deleteFile: 这个文件不能读取！");
            return false;
        }
        if (file.delete()) {
            Log.e(TAG, "deleteFile: 删除完成，搞定了！");
            return true;
        }
        Log.e(TAG, "deleteFile: 不知道咋回事就是没有删除成功");
        return false;
    }

    public OnImageDownloadListener onImageDownloadListener;

    public void setOnImageDownloadListener(OnImageDownloadListener onImageDownloadListener) {
        this.onImageDownloadListener = onImageDownloadListener;
    }

    public interface OnImageDownloadListener {
        void onImageDownload(boolean isSuccess, String url, File imageFile);
    }

//    public static int errorDrawableResId = 0;
//    public static int placeholderDrawableResId = 0;
//    public static int CACHE_IMAGE_SIZE = 250;
//    public static Context context;
//
//    // 初始化和清除缓存的东西
//
//    /**
//     * 初始化
//     *
//     * @param context 上下文
//     */
//    public static void init(Context context) {
//        init(context, CACHE_IMAGE_SIZE);
//    }
//
//    /**
//     * 初始化
//     *
//     * @param context      上下文
//     * @param cacheSizeInM Glide默认磁盘缓存最大容量250MB
//     */
//    public static void init(Context context, int cacheSizeInM) {
//        init(context, cacheSizeInM, MemoryCategory.NORMAL);
//    }
//
//    /**
//     * 初始化
//     *
//     * @param context        上下文
//     * @param cacheSizeInM   Glide默认磁盘缓存最大容量250MB
//     * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) ／ NORMAL(1f) ／ HIGH(1.5f);
//     */
//    public static void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory) {
//        init(context, cacheSizeInM, memoryCategory, true);
//    }
//
//    /**
//     * 初始化
//     *
//     * @param context        上下文
//     * @param cacheSizeInM   Glide默认磁盘缓存最大容量250MB
//     * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) ／ NORMAL(1f) ／ HIGH(1.5f);
//     * @param isInternalCD   true 磁盘缓存到应用的内部目录 / false 磁盘缓存到外部存
//     */
//    public static void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
//        GlideImageLoader.context = context;
//        Glide.get(context).setMemoryCategory(memoryCategory); // 根据给定的 MemoryCategory 调整 Glide 的最大内存
//        if (isInternalCD) {
//            new GlideBuilder().setDiskCache(new InternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
//        } else {
//            new GlideBuilder().setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
//        }
//    }
//
//    public static void trimMemory(int level) {
//        // 程序在内存清理的时候执行
//        Glide.get(GlideImageLoader.context).trimMemory(level);
//    }
//
//    public static void lowMemory() {
//        if (Looper.myLooper() != Looper.getMainLooper()) {
//            new Handler(Looper.getMainLooper()).post(new Runnable() {
//                @Override
//                public void run() {
//                    Glide.get(GlideImageLoader.context).clearMemory();
//                }
//            });
//        } else {
//            Glide.get(GlideImageLoader.context).clearMemory();
//        }
//    }
//
//    /**
//     * 默认加载图片
//     *
//     * @param context   上下文
//     * @param url       图片地址url
//     * @param imageView {@link ImageView}
//     */
//    public static void loadImage(Context context, String url, ImageView imageView) {
//        RequestOptions options = new RequestOptions()
//                .diskCacheStrategy(DiskCacheStrategy.ALL);
//        // DiskCacheStrategy.NONE：   表示不缓存任何内容。
//        // DiskCacheStrategy.SOURCE： 表示只缓存原始图片。
//        // DiskCacheStrategy.RESULT： 表示只缓存转换过后的图片（默认选项）。
//        // DiskCacheStrategy.ALL ：   表示既缓存原始图片，也缓存转换过后的图片。
//        Glide.with(context).load(url).apply(options).into(imageView);
//    }


}
